﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using SpeechLib;
using System.IO;
using NAudio.Wave;
using NAudio.Wave.SampleProviders;
using Newtonsoft.Json;
using System.Net;
using System.Web;
using System.Configuration;
using Baidu.Aip.Speech;
namespace TtsSpeech
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        Tts _baiduTtsClient = null;

        Tts BaiduTtsClient
        {
            get
            {
                if (_baiduTtsClient == null)
                {
                    _baiduTtsClient = new Tts(ConfigurationManager.AppSettings["baidukey"], ConfigurationManager.AppSettings["baidusecret"]);
                }
                return _baiduTtsClient;
            }
        }


        private void btnSpeak_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(this.textBox1.Text))
            {
                MessageBox.Show("请输入文本");
                return;
            }
            if (string.IsNullOrEmpty(this.textBox2.Text))
            {
                MessageBox.Show("请输入生成文件名称");
                return;
            }
            this.btnSpeak.Enabled = false;
            string path = Path.Combine(Environment.CurrentDirectory, "output");
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            var fileName = Path.Combine(path, this.textBox2.Text + ".wav");
            if (this.radioButton1.Checked)
            {
                SAPITts(this.textBox1.Text, fileName);
            }
            else if (this.radioButton3.Checked)
            {
                BaiduTts(this.textBox1.Text, fileName);
            }else if (this.radioButton2.Checked)
            {
                XFTts(this.textBox1.Text, fileName);
            }
            this.btnSpeak.Enabled = true;
        }

        public void SAPITts(string text, string fileName)
        {
            try
            {
                SpVoice voice = new SpVoice();
                var str = new SpFileStream();
                voice.Voice = new SpObjectToken() {  };
                str.Open(fileName, SpeechStreamFileMode.SSFMCreateForWrite);
                voice.AudioOutputStream = str;
                voice.Speak(text);
                str.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"发生错误:{ex.ToString()}");
            }
        }

        public void XFTts(string text, string fileName)
        {
            var param = new XFTtsParam()
            {
                auf = "audio/L16;rate=16000",
                aue = "raw",
                voice_name = "xiaofeng",
                speed = "80",
                volume = "50",
                pitch = "50",
                engine_type = "intp65",
                text_type = "text"
            };
            Post(param, text, fileName);
        }

        public void BaiduTts(string text, string fileName)
        {
            try
            {
                var option = new Dictionary<string, object>()
                {
                    {"spd", 5}, // 语速
                    {"vol", 7}, // 音量
                    {"per", 1 }  //发音人
                };
                var result = BaiduTtsClient.Synthesis(text, option);
                if (result.ErrorCode == 0)  // 或 result.Success
                {
                    fileName = fileName.Replace(".wav", ".mp3");
                    if (File.Exists(fileName))
                    {
                        File.Delete(fileName);
                    }
                    File.WriteAllBytes(fileName, result.Data);
                }
                else
                {
                    MessageBox.Show($"合成出错:{result.ErrorCode}_{result.ErrorMsg}");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"合成出错:{ex.ToString()}");
            }
        }

        public void mix(string tts, string bg)
        {
            var file = tts.Replace(".wav", "");
            using (WaveFileReader reader = new WaveFileReader(tts))
            {
                var newFormat = new WaveFormat(8000, 8, 1);
                using (var pcmStream = new WaveFormatConversionStream(newFormat, reader))
                {
                    WaveFileWriter.CreateWaveFile(file + "_128.wav", pcmStream);
                }

            }


            using (var reader1 = new AudioFileReader(file + "_128.wav"))
            using (var reader2 = new AudioFileReader(@"E:\freeswitch\cscript_tts_vbs\music.wav"))
            {
                reader1.Volume = 0.25f;
                reader2.Volume = 1;
                var mixer = new MixingSampleProvider(new[] { reader1, reader2 });
                WaveFileWriter.CreateWaveFile16(tts.Replace(".wav", "") + "_mix.wav", mixer);
            }
        }

        void Post(XFTtsParam xParam, string text, string fileName)
        {
            var apiKey = ConfigurationManager.AppSettings["xfkey"];
            var appId = ConfigurationManager.AppSettings["xfid"];
            var curTime = TextUtility.GetTimeStamp();
            var base64Param = xParam.Base64Param();
            var checkSum = TextUtility.MD5Encrypt32(apiKey + curTime + base64Param);

            HttpWebRequest request = null;
            request = WebRequest.Create("http://api.xfyun.cn/v1/service/v1/tts") as HttpWebRequest;
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded; charset=utf-8";
            request.Headers.Add("X-Appid", appId);
            request.Headers.Add("X-Param", base64Param);
            request.Headers.Add("X-CurTime", curTime);
            request.Headers.Add("X-CheckSum", checkSum);

            using (Stream stream = request.GetRequestStream())
            {
                byte[] data = Encoding.UTF8.GetBytes("text=" + HttpUtility.UrlEncode(text, System.Text.Encoding.UTF8));
                stream.Write(data, 0, data.Length);
            }

            var ret = request.GetResponse() as HttpWebResponse;
            if (ret.ContentType.Contains("audio/mpeg"))
            {
                byte[] buffer = new byte[512];
                using (Stream s = ret.GetResponseStream())
                {
                    using (FileStream writer = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write))
                    {
                        int c = 0;
                        while ((c = s.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            writer.Write(buffer, 0, c);
                        }
                    }
                }
            }
            else
            {
                using (Stream s = ret.GetResponseStream())
                {


                    using (StreamReader reader = new StreamReader(s))
                    {
                        var strRet = reader.ReadToEnd();
                        MessageBox.Show("合成失败:" + strRet);
                    }
                }
            }
        }
    }

    class XFTtsParam
    {
        public string auf { get; set; }
        public string aue { get; set; }
        public string voice_name { get; set; }
        public string speed { get; set; }
        public string volume { get; set; }
        public string pitch { get; set; }
        public string engine_type { get; set; }
        public string text_type { get; set; }

        public string Base64Param()
        {
            return TextUtility.EncodeBase64("utf-8", JsonConvert.SerializeObject(this));
            //return TextUtility.EncodeBase64("utf-8", str);
        }
    }
}
